/***********************************************************************
    filename:   DaterEventManager.cpp
    created:    10/4/2012
    author:     4Ys

    purpose:    Implements a base class for event manager
*************************************************************************/

#include "DaterEventManager.h"
#include "DaterEventFactory.h"
#include "DaterEventFacotryManager.h"

namespace Dater{
	//----------------------------------------------------------------------------//
	// singleton instance pointer
	template<> EventManager* Singleton<EventManager>::ms_Singleton	= 0;

	unsigned long EventManager::_uid_counter = 1;

	//----------------------------------------------------------------------------//
	EventManager::EventManager(void)
	{
		//get _uid_counter from database
	}

	//----------------------------------------------------------------------------//
	EventManager::~EventManager(void)
	{
		destroyAllEvents();
	}

	//----------------------------------------------------------------------------//
	Event* EventManager::createEvent(const std::string& type, const std::string& name,const Time& startTime, 
			const Time& finishTime, const std::string& description, int userID)
	{
		std::string finalName = name; 

		EventFactoryManager& efMgr = EventFactoryManager::getSingleton();
		EventFactory* factory = efMgr.getFactory(type);

		Event* newEvent = factory->createEvent(finalName, startTime, finishTime, description, userID, _uid_counter);
		_uid_counter++;
		//update the database

		EventIdentifier eventIdentifier;
		eventIdentifier.event_id = _uid_counter;
		eventIdentifier.user_id = userID;
		_eventRegistry[eventIdentifier] = newEvent;

		return newEvent;
	}

	//----------------------------------------------------------------------------//
	Event* EventManager::addEvent(const std::string& type, const std::string& name, const Time& startTime, 
	const Time& finishTime, const Time& createTime, const std::string& description, int userID, int eventID)
	{
		EventIdentifier eventIdentifier;
		eventIdentifier.event_id = eventID;
		eventIdentifier.user_id = userID;

		if (isEventPresent(eventIdentifier))
		{
			return getEvent(eventIdentifier);
		}

		EventFactoryManager& efMgr = EventFactoryManager::getSingleton();
		EventFactory* factory = efMgr.getFactory(type);

		Event* newEvent = factory->createEvent(name, startTime, finishTime, description, userID, eventID);
		newEvent->setCreateTime(createTime);

		_eventRegistry[eventIdentifier] = newEvent;

		return newEvent;
	}

	//----------------------------------------------------------------------------//
	void EventManager::destroyEvent(Event* theEvent)
	{
		if (theEvent)
		{
			int eventID = theEvent->getEventID();
			int userID = theEvent->getUserID();
			EventIdentifier eventIdentifier;
			eventIdentifier.event_id = eventID;
			eventIdentifier.user_id = userID;
			destroyEvent(eventIdentifier);
		}
	}

	//----------------------------------------------------------------------------//
	void EventManager::destroyEvent(EventIdentifier eventIdentifier)
	{
		EventRegistry::iterator evtpos = _eventRegistry.find(eventIdentifier);
		if (evtpos != _eventRegistry.end())
		{
			Event* evt = evtpos->second;
			_eventRegistry.erase(evtpos);
			
			delete evt;
		}
	}

	//----------------------------------------------------------------------------//
	Event* EventManager::getEvent(EventIdentifier eventIdentifier) const
	{
		EventRegistry::const_iterator pos = _eventRegistry.find(eventIdentifier);

		if (pos == _eventRegistry.end())
		{
			//exception! the event does not exist.
		}

		return pos->second;
	}

	//----------------------------------------------------------------------------//
	bool EventManager::isEventPresent(EventIdentifier eventIdentifier) const
	{
		return (_eventRegistry.find(eventIdentifier) != _eventRegistry.end());
	}

	//----------------------------------------------------------------------------//
	void EventManager::destroyAllEvents(void)
	{
		EventIdentifier eventIdentifier;
		while (!_eventRegistry.empty())
		{
			eventIdentifier = _eventRegistry.begin()->first;
			destroyEvent(eventIdentifier);
		}
	}

	//----------------------------------------------------------------------------//
	void EventManager::renameEvent(EventIdentifier eventIdentifier, const std::string& new_name)
	{
		renameEvent(getEvent(eventIdentifier),new_name);
	}

	//----------------------------------------------------------------------------//
	void EventManager::renameEvent(Event* theEvent, const std::string& new_name)
	{
		if (theEvent)
		{
			EventIdentifier eventIdentifier;
			eventIdentifier.event_id = theEvent->getEventID();
			eventIdentifier.user_id = theEvent->getUserID();
			EventRegistry::iterator pos = _eventRegistry.find(eventIdentifier);

			if (pos != _eventRegistry.end())
			{
				theEvent->setName(new_name);
			}
		}
	}

	//----------------------------------------------------------------------------//
	EventManager::EventIterator EventManager::getIterator(void) const
	{
		 return EventIterator(_eventRegistry.begin(), _eventRegistry.end());
	}

	//----------------------------------------------------------------------------//
	void EventManager::setUidCounter(unsigned long counter)
	{
		_uid_counter = counter;
	}

	//----------------------------------------------------------------------------//
	unsigned long EventManager::getUidCounter()
	{
		return _uid_counter;
	}
}